﻿using MMK.Paket_Tracker.Runtime;
using System;
using MMK.Paket_Tracker.Runtime.Helper;
using System.IO;
using System.Xml;
using System.IO.Ports;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Threading;

namespace MMK.Paket_Tracker.GUI.Models
{
    /// <summary>
    /// Model for GetWeight data
    /// </summary>
    public class GetWeightModel : ModelBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GetWeightModel"/> class.
        /// </summary>
        public GetWeightModel()
        {
            serialPort = new SerialPort();

            node = Setup.ReadNode(Directory.GetCurrentDirectory() + "\\Paket_Tracker_Customer_Terminal.config", "ComPortSettings");
            serialPort.PortName = node.Attributes["PortName"].Value;
            serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), node.Attributes["Parity"].Value);
            serialPort.BaudRate = Int32.Parse(node.Attributes["BaudRate"].Value);
            serialPort.DataBits = Int32.Parse(node.Attributes["DataBits"].Value);
            serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), node.Attributes["StopBits"].Value);
            serialPort.ReadTimeout = Int32.Parse(node.Attributes["ReadTimeout"].Value);
            serialPort.WriteTimeout = Int32.Parse(node.Attributes["WriteTimeout"].Value);
            serialPort.NewLine = ((Char)Int32.Parse(node.Attributes["Endchar"].Value)).ToString();
            stringLength = Int32.Parse(node.Attributes["StringLength"].Value);
            serialPort.DtrEnable = Boolean.Parse(node.Attributes["DtrEnable"].Value);
            serialPort.RtsEnable = Boolean.Parse(node.Attributes["RtsEnable"].Value);
            serialPort.Open();
            serialPort.DiscardInBuffer();
            serialPort.Write(Char.ConvertFromUtf32(27) + "B");
            serialPort.Write(Char.ConvertFromUtf32(27) + "T");
            _factory.StartNew(() => ReadValues());
            
        }

        void ReadValues()
        {
            serialData = new Runtime.SerialData(node);

            while (continueReading)
            {
                try
                {
                    rawData = serialPort.ReadLine();
                    if (rawData.Length == (stringLength - 1))
                    {
                        serialData.RawData = rawData;
                        RaisePropertyChanged("RawValue");
                        CheckPrice();
                    }

                }
                catch (TimeoutException ex)
                {
                    serialPort.Close();
                    System.Windows.MessageBox.Show("Die Daten von der Waage können nicht gelesen werden.\nKeine Preisermitllung möglich!\n\n" +
                        "Bitte wenden Sie sich an einen unserer Mitarbeiter!", "Bär-Paket: Meldung",
                        System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
                    continueReading = false;
                }                
            }
        }

        private void CheckPrice()
        {
            if (serialData.BalValue > 0.01 && !String.IsNullOrEmpty(serialData.Unit.Replace(" ","")))
            {
                if (serialData.BalValue <= .5)
                {
                    price = 1.60M;
                }
                else if (serialData.BalValue <= 1)
                {
                    price = 2.3M;
                }
                else if (serialData.BalValue <= 1.5)
                {
                    price = 2.9M;
                }
                else if (serialData.BalValue <= 2)
                {
                    price = 3.4M;
                }
                else if (serialData.BalValue <= 5)
                {
                    price = 5.1M;
                }
                else if (serialData.BalValue <= 10)
                {
                    price = 9.2M;
                }
                HasError = false;
                continueReading = false;
                RaisePropertyChanged("Price");
            }
        }

        /// <summary>
        /// Gets the raw value.
        /// </summary>
        /// <value>The raw value.</value>
        public String RawValue 
        {
            get
            {
                if (serialData == null)
                {
                    return String.Empty;
                }
                return serialData.RawData;  
            }
        }

        /// <summary>
        /// Gets the unit.
        /// </summary>
        /// <value>The unit.</value>
        public String Unit
        {
            get
            {
                if (serialData == null)
                {
                    return String.Empty;
                }
                return serialData.Unit;
            }
        }

        /// <summary>
        /// Gets the balance value.
        /// </summary>
        /// <value>The balance value.</value>
        public Double BalValue
        {
            get
            {
                if (serialData == null)
                {
                    return 0;
                }
                return serialData.BalValue;
            }
        }

        /// <summary>
        /// Gets the price.
        /// </summary>
        /// <value>The price.</value>
        public String Price
        {
            get
            {
                if (price == 0M)
                {
                    return String.Empty;
                }
                else
                {
                    return price.ToString("G");
                }
            }
        }


        /// <summary>
        /// Gets or sets a value indicating whether this instance has an error.
        /// </summary>
        /// <value><c>true</c> if this instance has an error; otherwise, <c>false</c>.</value>
        public Boolean HasError
        {
            get { return hasError; }
            set { hasError = value; }
        }

        private Boolean hasError = true;
        private XmlNode node;
        private SerialPort serialPort;
        private TaskFactory _factory = new TaskFactory(
                                          TaskCreationOptions.AttachedToParent,
                                          TaskContinuationOptions.AttachedToParent);
        private String rawData;
        private Boolean continueReading = true;
        private MMK.Paket_Tracker.Runtime.SerialData serialData;
        private Int32 stringLength;
        private Decimal price;
    }
}
